package edu.whu.puppygo.controller;

import edu.whu.puppygo.assistant.HealthAssistant;
import edu.whu.puppygo.base.HttpResponse;
import edu.whu.puppygo.dao.ConversationDao;
import edu.whu.puppygo.dao.FragmentDao;
import edu.whu.puppygo.dto.FragmentDto;
import edu.whu.puppygo.entity.Conversation;
import edu.whu.puppygo.entity.Fragment;
import edu.whu.puppygo.entity.FragmentStatueEnum;
import edu.whu.puppygo.entity.PetMatter;
import edu.whu.puppygo.service.ConversationService;
import edu.whu.puppygo.util.GlobalUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.MediaType;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;

/**
 * @author guanruwang
 * @date 2023/11/22$
 */
@RestController
@Slf4j
@RequestMapping("/conversation")
public class ConversationController {
    @Resource
    private FragmentDao fragmentDao;
    @Resource
    private ConversationService conversationService;
    @Resource
    private ConversationDao conversationDao;

    @Resource
    private HealthAssistant agent;

    @GetMapping("")
    public HttpResponse<List<Conversation>> getConversation(int pageSize, int pageNum) {
        Long id = GlobalUser.getUser().getId();
        Pageable pageable = PageRequest.of(pageNum, pageSize);
        List<Conversation> res = conversationDao.findByUserId(id, pageable);
        return HttpResponse.success(res);
    }

    @GetMapping("/{conversationId}")
    public HttpResponse<Conversation> getConversation(@PathVariable long conversationId) {
        Conversation res = conversationDao.findById(conversationId).orElseThrow(() -> new RuntimeException("会话不存在"));
        return HttpResponse.success(res);
    }

    @PostMapping("/{petId}")
    public HttpResponse<Conversation> addConversation(@PathVariable long petId) {
        log.info("petId:{}", petId);
        Conversation conversation = conversationService.addConversation(petId);
        return HttpResponse.success(conversation);
    }

    @PutMapping("/{conversationId}/{name}")
    public HttpResponse<String> updateConversation(@PathVariable long conversationId, @PathVariable String name) {
        Conversation res = conversationDao.findById(conversationId).orElseThrow(() -> new RuntimeException("会话不存在"));
        res.setName(name);
        conversationDao.save(res);
        return HttpResponse.success("ok");
    }

    @PostMapping("/fragment")
    public HttpResponse<Long> addFragment(FragmentDto fragmentDto, @RequestParam(value = "file", required = false) MultipartFile mpfile) {
        log.info("fragmentDto:{}", fragmentDto);
        if (mpfile != null) {
            fragmentDto.setImage(mpfile);
        }
        Fragment fragment = conversationService.addFragment(fragmentDto);
        return HttpResponse.success(fragment.getId());
    }

    @GetMapping("/fragment/statue")
    public HttpResponse<FragmentStatueEnum> getStatue(long fragmentId) {
        FragmentStatueEnum statue = fragmentDao.findById(fragmentId).orElseThrow(() -> new RuntimeException("片段不存在")).getStatue();
        return HttpResponse.success(statue);
    }

    @GetMapping("/fragment/{fragmentId}")
    public HttpResponse<Fragment> getFragment(@PathVariable long fragmentId) {
        Fragment fragment = fragmentDao.findById(fragmentId).orElseThrow(() -> new RuntimeException("片段不存在"));
        return HttpResponse.success(fragment);
    }

    //流式输出
//    @GetMapping(value = "/fragment/{fragmentId}/answer", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
//    public ResponseEntity<StreamingResponseBody> streamFragmentAnswer(@PathVariable long fragmentId) {
//        Fragment fragment = fragmentDao.findById(fragmentId)
//                .orElseThrow(() -> new RuntimeException("片段不存在"));
//
//        StreamingResponseBody responseBody = outputStream -> {
//            try {
//                String answer = fragment.getAnswer();
//                byte[] bytes = answer.getBytes();
//                for (byte b : bytes) {
//                    outputStream.write(b);
//                    outputStream.flush();
//                    Thread.sleep(10); // 10毫秒的延迟，可以根据需要调整
//                }
//            } catch (IOException | InterruptedException e) {
//                throw new RuntimeException("无法流式传输片段答案");
//            }
//        };
//
//        HttpHeaders headers = new HttpHeaders();
//        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//        headers.setContentDispositionFormData("filename", "answer.txt");
//
//        return new ResponseEntity<>(responseBody, headers, HttpStatus.OK);
//    }

    @GetMapping("/fragment/{fragmentId}/answer")
    public void streamFragmentAnswer(@PathVariable long fragmentId) {
        Fragment fragment = fragmentDao.findById(fragmentId)
                .orElseThrow(() -> new RuntimeException("片段不存在"));

        try (ServerSocket serverSocket = new ServerSocket(8081)) {
            log.info("Socket server started");
            while (true) {
                Socket clientSocket = serverSocket.accept();
                System.out.println("Client connected: " + clientSocket.getInetAddress());

                try (OutputStream outputStream = clientSocket.getOutputStream()) {
                    String answer = fragment.getAnswer();
                    byte[] bytes = answer.getBytes();
                    for (byte b : bytes) {
                        outputStream.write(b);
                        outputStream.flush();
                        Thread.sleep(10); // 10毫秒的延迟
                    }
                    System.out.println("Data sent to client");
                } catch (IOException | InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    clientSocket.close();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
//    @GetMapping("/fragment/{fragmentId}/answer")
//    public void streamFragmentAnswer(@PathVariable long fragmentId) {
//        Fragment fragment = fragmentDao.findById(fragmentId)
//                .orElseThrow(() -> new RuntimeException("片段不存在"));
//
//        try (ServerSocket serverSocket = new ServerSocket(8080)) {
//            log.info("Socket server started");
//
//            while (true) {
//                Socket clientSocket = serverSocket.accept();
//                System.out.println("Client connected: " + clientSocket.getInetAddress());
//
//                try (OutputStream outputStream = clientSocket.getOutputStream()) {
//                    String answer = fragment.getAnswer();
//                    byte[] bytes = answer.getBytes();
//                    outputStream.write(bytes);
//                    outputStream.flush();
//                    System.out.println("Data sent to client");
//                } catch (IOException e) {
//                    log.error("Error while sending data to client", e);
//                } finally {
//                    try {
//                        clientSocket.close();
//                    } catch (IOException e) {
//                        log.error("Error while closing client socket", e);
//                    }
//                }
//            }
//        } catch (IOException e) {
//            log.error("Error while initializing server socket", e);
//        }
//    }

    @GetMapping("/fragment/advice/{fragmentId}")
    public HttpResponse<PetMatter> getAdvice(@PathVariable long fragmentId) {
        Fragment fragment = fragmentDao.findById(fragmentId).orElseThrow(() -> new RuntimeException("片段不存在"));
        PetMatter advice = agent.getAdvice(fragment.getConversationId(), fragment.getAnswer());
        return HttpResponse.success(advice);
    }

}
